from fastapi import APIRouter, UploadFile, HTTPException, Depends
from sqlmodel.ext.asyncio.session import AsyncSession
from pydantic import BaseModel
from schemas.common import ResponseFile
from schemas.common import RETURN 
from datetime import datetime
import os
import base64
import shutil
from core.Config import settings
from addons.Oss import Aly
from core.Log import log_admin_event

from database.mysql import get_async_session
import models.admin.system.Admin as AdminModel
import models.admin.system.Attachment as AttachmentModel
from core.Depend import check_token
class Base64Request(BaseModel):
    base64str: str
    
# 回头重构进入配置页面
UPLOAD_DIRECTORY = settings.UPLOAD_DIRECTORY
ALLOWED_EXTENSIONS = settings.ALLOWED_EXTENSIONS
MAX_FILE_SIZE = settings.MAX_FILE_SIZE
STATIC_PREFIX = settings.STATIC_PREFIX


def is_file_size_allowed(file_size: int) -> bool:
    return file_size <= MAX_FILE_SIZE

def is_extension_allowed(file_extension: str) -> bool:
    return file_extension in ALLOWED_EXTENSIONS

if not os.path.exists(UPLOAD_DIRECTORY):
    os.makedirs(UPLOAD_DIRECTORY)


router = APIRouter(tags=["文件上传"])

# 文件上传 , user: AdminModel.redis_admin = Depends(check_token) 
@router.post("/uploadfiles",response_model=RETURN[ResponseFile])
async def create_file(file: UploadFile, session: AsyncSession = Depends(get_async_session), user: AdminModel.redis_admin = Depends(check_token)):
    try:
        imagewidth = 0
        imageheight = 0
        imagetype = ""
        imageframes = 0
        storage = "local"
        file_extension = file.filename.split(".")[-1]
      
        if settings.OSS:
            storage = "oss"
            full_path, path,imagewidth, imageheight, imagetype, imageframes = await Aly.upload_file(file)
            log_admin_event(f"文件上传成功{full_path}")
        else:
            # 使用当前日期（格式：YYYY-MM-DD）创建一个文件夹
            date_now = datetime.now().strftime("%Y-%m-%d")
            FILE_UPLOAD_DIRECTORY = settings.STATIC_DIR + UPLOAD_DIRECTORY
            upload_folder = os.path.join(FILE_UPLOAD_DIRECTORY, date_now)
            os.makedirs(upload_folder, exist_ok=True)
            # 使用当前时间戳来创建一个文件名，保持文件的扩展名不变
            filename, file_extension = os.path.splitext(file.filename)
            file_extension = file_extension.lstrip(".").lower()
            # 检查文件格式
            if not is_extension_allowed(file_extension):
                return RETURN.fail(data=f"File type {file_extension} not allowed")

            timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f")
            new_filename = f"{timestamp}.{file_extension}"
            file_location = os.path.join(upload_folder, new_filename)
            with open(file_location, "wb+") as file_object:
                # 将上传的文件保存到文件系统
                shutil.copyfileobj(file.file, file_object)
            path = UPLOAD_DIRECTORY + "/" + date_now + "/" + new_filename
            full_path = STATIC_PREFIX+path

            # 如果是图片，获取图片的宽高信息
            if file.content_type.startswith("image"):
                from PIL import Image
                with Image.open(file_location) as img:
                    imagewidth, imageheight = img.size
                    imagetype = img.format
                    imageframes = 0
                    if hasattr(img, 'n_frames'):
                        imageframes = img.n_frames
         

        imagetype = imagetype if imagetype else file_extension

        # TODO: 保存附件信息到数据库
        attachment = AttachmentModel.Attachment(
            category="默认分类",
            admin_id=user.admin.id,
            url=path,
            imagewidth=imagewidth,
            imageheight=imageheight,
            imagetype=imagetype,
            imageframes=imageframes,
            filename=file.filename,
            filesize=file.file._file.tell(),
            mimetype=file.content_type,
            extparam="",
            storage=storage,
        )
        session.add(attachment)
        await session.commit()
        return RETURN.success(data=ResponseFile(full_path=full_path,path=path))
    except Exception as e:
        log_admin_event(f"文件上传失败"+str(e))
        raise HTTPException(status_code=500, detail="File upload failed")
    finally:
        # 确保文件资源被正确清理
        file.file.close()



# base64上传
@router.post("/uploadBase64", response_model=RETURN[ResponseFile])
async def upload_base64(request: Base64Request, user: AdminModel.redis_admin = Depends(check_token), session: AsyncSession = Depends(get_async_session)):
    try:
        base64str = request.base64str
        # 检查 Base64 数据是否存在
        if not base64str:
            raise HTTPException(status_code=400, detail="Base64 data is required")

        # 处理可能存在的 Base64 头信息
        if "," in base64str:
            base64_data = base64str.split(",")[1]
        else:
            base64_data = base64str

        # 解码 Base64 数据
        try:
            file_data = base64.b64decode(base64_data)
        except Exception as e:
            raise HTTPException(status_code=400, detail="Invalid Base64 data")

        # 使用当前日期（格式：YYYY-MM-DD）创建一个文件夹
        date_now = datetime.now().strftime("%Y-%m-%d")
        FILE_UPLOAD_DIRECTORY = settings.STATIC_DIR + UPLOAD_DIRECTORY
        upload_folder = os.path.join(FILE_UPLOAD_DIRECTORY, date_now)
        os.makedirs(upload_folder, exist_ok=True)

        # 使用当前时间戳来创建一个文件名
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f")
        new_filename = f"{timestamp}.png"  # 假设图片是 PNG 格式，你可以根据需求修改此处

        file_location = os.path.join(upload_folder, new_filename)

        # 将解码后的二进制数据写入文件
        with open(file_location, "wb") as file_object:
            file_object.write(file_data)

        # 构建返回的路径
        path = UPLOAD_DIRECTORY + "/" + date_now + "/" + new_filename
        # TODO: 保存附件信息到数据库
        attachment = AttachmentModel.Attachment(
            category="base64",
            admin_id=user.admin.id,
            url=path,
            imagewidth=0,
            imageheight=0,
            imagetype="png",
            imageframes=0,
            filename=new_filename,
            filesize=len(file_data),
            mimetype="image/png",
            extparam="",
            storage="local",
        )
        session.add(attachment)
        await session.commit()
        return RETURN.success(data=ResponseFile(full_path=STATIC_PREFIX+path,path=path))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"File upload failed: {str(e)}")